package com.alibaba.cloud.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;

import org.apache.commons.lang3.StringUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * The Class DateUtil.
 *
 * @ClassName: DateTimeUtil
 * @Description:日期处理工具类
 * @author: zhb1316783262@163.com
 * @date: 2019年2月21日下午2:10:42
 */
@Slf4j
public class DateUtil {

	/** The Constant DATE_FORMAT. */
	// 年月日
	public static final String DATE_FORMAT = "yyyy-MM-dd";

	/** The Constant DATETIME_FORMAT. */
	// 年月日 时分秒
	public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

	/** The Constant ZONE_ID. */
	public static final ZoneId ZONE_ID = ZoneOffset.UTC;

	/**
	 * Str to local date.
	 *
	 * @param dateTimeStr the date time str
	 * @return the local date time
	 */
	// str->LocalDate
	public static LocalDate strToLocalDate(String dateStr) {
		return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(DATE_FORMAT));
	}

	/**
	 * Str to local date time.
	 *
	 * @param dateTimeStr the date time str
	 * @return the local date time
	 */
	// str->LocalDateTime
	public static LocalDateTime strToLocalDateTime(String dateTimeStr) {
		return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(DATETIME_FORMAT));
	}

	/**
	 * Str to date.
	 *
	 * @param dateTimeStr the date time str
	 * @return the date
	 */
	// str->Date
	public static Date strToDate(String dateStr) {
		LocalDateTime dateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(DATE_FORMAT));
		ZoneId zoneId = ZoneId.systemDefault();
		return Date.from(dateTime.atZone(zoneId).toInstant());
	}

	/**
	 * Str to date.
	 *
	 * @param dateTimeStr the date time str
	 * @return the date
	 */
	// str->Date
	public static Date strToDate(String dateStr, String dateFormat) {
		LocalDate localDate = LocalDate.from(LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(dateFormat)));
		ZoneId zone = ZoneId.systemDefault();
		Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
		return Date.from(instant);
	}

	/**
	 * Str to date time.
	 *
	 * @param dateTimeStr the date time str
	 * @return the date
	 */
	// str->DateTime
	public static Date strToDateTime(String dateTimeStr) {
		LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(DATETIME_FORMAT));
		ZoneId zoneId = ZoneId.systemDefault();
		return Date.from(dateTime.atZone(zoneId).toInstant());
	}

	/**
	 * Date to str.
	 *
	 * @param date      the date
	 * @param formatStr the format str
	 * @return the string
	 */
	// Date->str
	public static String dateToStr(Date date, String formatStr) {
		if (date == null) {
			return StringUtils.EMPTY;
		}
		Instant instant = date.toInstant();
		ZoneId zoneId = ZoneId.systemDefault();
		LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
		return DateTimeFormatter.ofPattern(formatStr).format(localDateTime);
	}

	/**
	 * Date to str.
	 *
	 * @param date the date
	 * @return the string
	 */
	// Date->str
	public static String dateToStr(Date date) {
		if (date == null) {
			return StringUtils.EMPTY;
		}
		Instant instant = date.toInstant();
		ZoneId zoneId = ZoneId.systemDefault();
		LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
		return DateTimeFormatter.ofPattern(DATETIME_FORMAT).format(localDateTime);
	}

	/**
	 * @Description: 时间转LocalDateTime
	 * @author: zhb1316783262@163.com
	 * @date: 2024年6月6日下午5:59:38
	 */
	public static LocalDateTime dateToLocalDate(Date date) {
		return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
	}

	public static String localDateTimeToStr(LocalDateTime date) {
		if (date == null) {
			return StringUtils.EMPTY;
		}
		return DateTimeFormatter.ofPattern(DATETIME_FORMAT).format(date);
	}

	/**
	 * @Description: 计算两个日期之间的差距
	 * @author: zhb1316783262@163.com
	 * @date: 2024年6月6日下午5:57:40
	 */
	public static int differentDays(Date date1, Date date2) {
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);

		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		int day1 = cal1.get(Calendar.DAY_OF_YEAR);
		int day2 = cal2.get(Calendar.DAY_OF_YEAR);

		int year1 = cal1.get(Calendar.YEAR);
		int year2 = cal2.get(Calendar.YEAR);
		if (year1 != year2) // 同一年
		{
			int timeDistance = 0;
			for (int i = year1; i < year2; i++) {
				if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) // 闰年
				{
					timeDistance += 366;
				} else // 不是闰年
				{
					timeDistance += 365;
				}
			}
			return timeDistance + (day2 - day1);
		} else // 不同年
		{
			return day2 - day1;
		}
	}

	/***
	 * @description: 获取当前时间的前一周
	 * @date: 2022/3/28 18:53
	 * @author: zhuhb-a@glodon.com
	 */
	public static Date daysBefore(int days) {
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		calendar.add(Calendar.DATE, -days);
		String sevenDaysBefore = sdf.format(calendar.getTime());
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		LocalDate localDate = LocalDate.parse(sevenDaysBefore, dateTimeFormatter);
		return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
	}

	/**
	 * @Description: 多少分钟之前
	 * @author: zhb1316783262@163.com
	 * @date: 2024年6月6日下午6:01:28
	 */
	public static Date minutesAgo(int minutes) {
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_FORMAT);
		calendar.add(Calendar.MINUTE, -minutes);
		String sevenDaysBefore = sdf.format(calendar.getTime());
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATETIME_FORMAT);
		LocalDateTime localDate = LocalDateTime.parse(sevenDaysBefore, dateTimeFormatter);
		return Date.from(localDate.atZone(ZoneId.systemDefault()).toInstant());
	}

	public static Date today() {
		return Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
	}

	public static Date todayWithTime() {
		return Date.from(LocalDateTime.of(LocalDateTime.now().toLocalDate(), LocalTime.MIN)
				.atZone(ZoneId.systemDefault()).toInstant());
	}

	public static Date sevenDaysBeforeWithTime() {
		LocalDateTime localDateTimeNow = LocalDateTime.now().plusDays(-7);
		LocalDateTime localDateTime = LocalDateTime.of(localDateTimeNow.toLocalDate(), LocalTime.MIN);
		return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
	}

	/**
	 * @Description: 昨天
	 * @author: zhb1316783262@163.com
	 * @date: 2024年6月6日下午6:02:23
	 */
	public static Date yesterday() {
		LocalDateTime localDateTimeNow = LocalDateTime.now().plusDays(-1);
		return Date.from(LocalDateTime.of(localDateTimeNow.toLocalDate(), LocalTime.MIN).atZone(ZoneId.systemDefault())
				.toInstant());
	}

	/***
	 * @description: 当前年的第一天
	 * @author: zhuhb
	 * @date: 2022/5/26 9:02
	 */
	public static LocalDateTime firstDayOfYear() {
		// 某年的第一天
		return LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear()).withHour(0).withMinute(0).withSecond(0);
	}

	/***
	 * @description: 当前年的最后一天
	 * @author: zhuhb
	 * @date: 2022/5/26 9:02
	 */
	public static LocalDateTime lastDayOfYear() {
		// 某年的最后一天
		return LocalDateTime.now().with(TemporalAdjusters.lastDayOfYear()).withHour(23).withMinute(59).withSecond(59);
	}

	/***
	 * @description: 明天
	 * @author: zhuhb
	 * @date: 2022/5/26 9:02
	 */
	public static Date tomorrow() {
		LocalDateTime localDateTimeNow = LocalDateTime.now().plusDays(1);
		return Date.from(LocalDateTime.of(localDateTimeNow.toLocalDate(), LocalTime.MIN).atZone(ZoneId.systemDefault())
				.toInstant());
	}
	/***
	 * @description: 指定时间的下一天
	 * @author: zhuhb
	 * @date: 2022/5/26 9:02
	 */
	public static String getNextDay(String dateTime) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_FORMAT);
		Date date = null;
		try {
			date = simpleDateFormat.parse(dateTime);
		} catch (ParseException e) {
			log.error("String转Date日期失败:", e);
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		// 往后一天
		calendar.add(Calendar.DAY_OF_MONTH, 1);
		return simpleDateFormat.format(calendar.getTime());
	}

	/***
	 * 转成格林威治时间
	 *
	 * @param localDate 时间格式必须是yyyy-MM-dd HH:mm:ss
	 * 
	 * @return
	 */
	public static String localToGTM(String localDate) {
		if (StringUtils.isBlank(localDate)) {
			return null;
		}
		SimpleDateFormat format;
		format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
		Date result_date;
		long result_time = 0;

		if (null == localDate) {
			return localDate;
		} else {
			try {
				format.setTimeZone(TimeZone.getDefault());
				result_date = format.parse(localDate);
				result_time = result_date.getTime();
				format.setTimeZone(TimeZone.getTimeZone("GMT00:00"));
				return format.format(result_time);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return localDate;
	}

	/***
	 * LocalDateTime转Date
	 * @Description:
	 * @Author: ZHUHB
	 * @Date: 2023/7/20 15:03
	 **/
	public static Date localDateTimeToDate(LocalDateTime localDateTime) {
		return Objects.isNull(localDateTime) ? null
				: Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
	}
}
